﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;

namespace DbWord
{
    sealed class ParametersCache
    {
        static readonly ParametersCache instance = new ParametersCache();
        public static ParametersCache Instance
        {
            get { return instance; }
        }
        ParametersCache()
        {
            helper = new Request.Helper();
        }

        public void InitByDateTime(DateTime dt)
        {
            ParametersDic = InitParametersDic(dt);
            NormalSqlDic = InitNormalXElementDic(dt);
            ChartSqlDic = InitChartXElementDic(dt);
            DestFilename = InitDestFilename();
        }

        Request.Helper helper { get; set; }

        public Dictionary<string, DateTime> ParametersDic { get; set; }
        public Dictionary<string, XElement> NormalSqlDic { get; set; }
        public Dictionary<string, XElement> ChartSqlDic { get; set; }
        public string DestFilename { get; set; }

        Dictionary<string, DateTime> InitParametersDic(DateTime dt)
        {
            XDocument doc = XDocument.Load(Defs.XmlDocFile);
            var sdic = (from c in doc.Descendants("Parameter").Where(p => p.Attribute("src").Value == "sql")
                        select new
                        {
                            Key = c.Element("Name").Value.Trim(),
                            Sql = c.Element("Sql").Value.Trim()
                        });
            var dic = sdic.Select(o =>
            {
                var newp = new
                    {
                        Key = o.Key,
                        Val = helper.Idb.ExecuteScalar(string.Format(o.Sql,dt))
                    };
                return newp;
            }).ToDictionary(o => o.Key, o => Convert.ToDateTime(o.Val));

            return dic;
        }
        Dictionary<string, XElement> InitNormalXElementDic(DateTime dt)
        {
            XDocument doc = XDocument.Load(Defs.XmlDocFile);
            var sdic = (from c in doc.Descendants("Place").Elements("PlaceHolder")
                        select new
                        {
                            Key = c.Element("Name").Value.Trim(),
                            Node = c
                        });
            var dic = sdic.Select(o =>
            {
                var newp = new
                    {
                        Key = o.Key,
                        Val = ReplacePara(o.Node)
                    };
                return newp;
            }).ToDictionary(o => o.Key, o => o.Val);

            return dic;
        }
        Dictionary<string, XElement> InitChartXElementDic(DateTime dt)
        {
            XDocument doc = XDocument.Load(Defs.XmlDocFile);
            var sdic = (from c in doc.Descendants("Charts").Elements("Chart")
                        select new
                        {
                            Key = c.Element("Name").Value.Trim(),
                            Node = c
                        });
            var dic = sdic.Select(o =>
            {
                var newp = new
                    {
                        Key = o.Key,
                        Val = ReplacePara(o.Node)
                    };
                return newp;
            }).ToDictionary(o => o.Key, o => o.Val);


            return dic;
        }
        string InitDestFilename()
        {
            XDocument doc = XDocument.Load(Defs.XmlDocFile);
            var node = doc.Element("root").Element("FileName");
            node = ReplacePara(node);
            return helper.Idb.ExecuteScalar(node.Element("Sql").Value);
        }

        XElement ReplacePara(XElement xe)
        {
            foreach (KeyValuePair<string, DateTime> kvp in ParametersDic)
            {
                Regex r = new Regex(@"(?<![\{\\])(\{(" + kvp.Key + @")\})");
                MatchCollection mc = r.Matches(xe.Element("Sql").Value);
                foreach (Match match in mc)
                {
                    xe.Element("Sql").Value = xe.Element("Sql").Value.Replace(
                        match.Groups[1].Value
                        , kvp.Value.ToString("yyyyMMdd"));
                }
            }
            return xe;
        }
    }
}
